/*
# PostgreSQL Database Modeler (pgModeler)
#
# Copyright 2006-2018 - Raphael Araújo e Silva <raphael@pgmodeler.io>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# The complete text of GPLv3 is at LICENSE file on source code root directory.
# Also, you can get the complete GNU General Public License at <http://www.gnu.org/licenses/>
*/

/**
\ingroup libpgmodeler_ui
\class ModelDatabaseDiffForm
\brief Implements the operations to compare and generate a diff between model and database via form.
*/

#ifndef MODEL_DATABASE_DIFF_FORM
#define MODEL_DATABASE_DIFF_FORM

#include "ui_modeldatabasediffform.h"
#include "modelsdiffhelper.h"
#include "databaseimporthelper.h"
#include "modelexporthelper.h"
#include "hinttextwidget.h"
#include "syntaxhighlighter.h"
#include "htmlitemdelegate.h"
#include "numberedtexteditor.h"
#include <QThread>

class ModelDatabaseDiffForm: public QDialog, public Ui::ModelDatabaseDiffForm {
	private:
		Q_OBJECT

		NumberedTextEditor *sqlcode_txt;

		//! \brief Custom delegate used to paint html texts in output tree
		HtmlItemDelegate *htmlitem_del;

		//! \brief Hint texts used on the diff options
		HintTextWidget *apply_on_server_ht, *store_in_file_ht,
		*import_sys_objs_ht, *import_ext_objs_ht, *keep_cluster_objs_ht,
		*trunc_tables_ht, *ignore_errors_ht, *force_recreation_ht,
		*cascade_mode_ht, *pgsql_ver_ht, *recreate_unmod_ht,
		*keep_obj_perms_ht, *ignore_duplic_ht, *reuse_sequences_ht,
		*preserve_db_name_ht, *dont_drop_missing_objs_ht,
		*ignore_error_codes_ht, *drop_missing_cols_constr_ht;

		//! \brief Syntax highlighter used on the diff preview tab
		SyntaxHighlighter *sqlcode_hl;

		//! \brief Helper that will execute the diff between models
		ModelsDiffHelper *diff_helper;

		//! \brief Helper that will execute the database import
		DatabaseImportHelper *import_helper, *src_import_helper;

		//! \brief Helper that will execute the diff export to database
		ModelExportHelper *export_helper;

		//! \brief Threads that will execute each step: import, diff, export
		QThread *import_thread, *diff_thread, *export_thread, *src_import_thread;

		//! \brief Tree items generated in each diff step
		QTreeWidgetItem *import_item, *diff_item, *export_item, *src_import_item;

		/*! \brief This is the model used in the diff process representing the source.
		 * It can be the modelo loaded from file or a representation of the source database (when comparing two dbs) */
		DatabaseModel *source_model,

		//! \brief This is the model loaded from file
		*loaded_model,

		//! \brief This is the model generated by the reverse engineering step
		*imported_model;

		//! \brief Connection used to export the diff to database
		Connection *export_conn;

		//! \brief PostgreSQL version used by the diff process
		QString pgsql_ver;

		int diff_progress, curr_step, total_steps;

		bool process_paused;

		void closeEvent(QCloseEvent *event);
		void showEvent(QShowEvent *);

		//! \brief Creates the helpers and threads
		void createThread(unsigned thread_id);

		//! \brief Destroy the helpers and threads
		void destroyThread(unsigned thread_id);

		//! \brief Destroy the imported model
		void destroyModel(void);

		void clearOutput(void);
		void resetForm(void);
		void resetButtons(void);
		void saveDiffToFile(void);
		void finishDiff(void);

		//! \brief Constants used to reference the thread/helper to be handled in createThread() and destroyThread()
		static const unsigned SRC_IMPORT_THREAD=0,
		IMPORT_THREAD=1,
		DIFF_THREAD=2,
		EXPORT_THREAD=3;

	public:
		ModelDatabaseDiffForm(QWidget * parent = 0, Qt::WindowFlags f = 0);
		~ModelDatabaseDiffForm(void);

		void setModelWidget(ModelWidget *model_wgt);

	private slots:
		void listDatabases(void);
		void enableDiffMode(void);
		void generateDiff(void);
		void cancelOperation(bool cancel_by_user);
		void updateProgress(int progress, QString msg, ObjectType obj_type, QString cmd=QString());
		void updateDiffInfo(ObjectsDiffInfo diff_info);
		void captureThreadError(Exception e);
		void handleImportFinished(Exception e);
		void handleDiffFinished(void);
		void handleExportFinished(void);
		void handleErrorIgnored(QString err_code, QString err_msg, QString cmd);
		void selectOutputFile(void);
		void importDatabase(unsigned thread_id);
		void diffModels(void);
		void exportDiff(bool confirm=true);
		void filterDiffInfos(void);

	signals:
		/*! \brief This signal is emitted whenever the user changes the connections settings
		within this widget without use the main configurations dialog */
		void s_connectionsUpdateRequest(void);
};

#endif
